#include "engine.h"

engine::engine()
{
	//console = Console();
	quit = false;
	state = EDITOR;
	background = NULL;
	screen = NULL;
	text = NULL;
	font = NULL;
	timer = Timer();
	mousex = mousey = myrel = mxrel = 0;
	lmx = lmy = 0;
	c = Camera(0,0,800,800);
	elayer = 0;
	layers = std::list<lrecord>();
}

bool engine::Init()
{
	if(SDL_Init(SDL_INIT_EVERYTHING) == -1)
		return false;

	if(TTF_Init() == -1)
		return false;

	screen = SDL_SetVideoMode(800, 800, 32, SDL_SWSURFACE);

	SDL_WM_SetCaption("Scrap Book", NULL);

	return true;
}

int engine::getState()
{
	return state;
}

void engine::setState(int i)
{
	state = i;
}

void engine::apply_surface(int x, int y, SDL_Surface* source, SDL_Surface* destination, SDL_Rect* clip = NULL)
{
	SDL_Rect offset;

	offset.x = x;
	offset.y = y;

	SDL_BlitSurface(source, clip, destination, &offset);
}

SDL_Surface* engine::load_image(std::string filename)
{
	SDL_Surface *loadedImage = NULL;
	SDL_Surface *optimizedImage = NULL;

	loadedImage = IMG_Load(filename.c_str());

	if(loadedImage != NULL)
	{
		optimizedImage = SDL_DisplayFormat(loadedImage);

		SDL_FreeSurface(loadedImage);
	}

	//Here be dinosaur code
	/*if(optimizedImage != NULL)
	{
		Uint32 colorkey = SDL_MapRGB(optimizedImage->format,255,255,255);
		SDL_SetColorKey(optimizedImage, SDL_SRCCOLORKEY, colorkey);
	}*/

	return optimizedImage;
}

bool engine::CollisionCheck(SDL_Rect A, SDL_Rect B)
{
	int leftA, leftB;
	int rightA, rightB;
	int topA, topB;
	int bottomA, bottomB;

	leftA = A.x;
	rightA = A.x + A.w;
	topA = A.y;
	bottomA = A.y + A.h;

	leftB = B.x;
	rightB = B.x + B.w;
	topB = B.y;
	bottomB = B.y + B.h;

	if( bottomA <= topB )
	{
		return false;
	}

	if( topA >= bottomB )
	{
		return false;
	}

	if( rightA <= leftB )
	{
		return false;
	}

	if( leftA >= rightB )
	{
		return false;
	}

	return true;
}

bool engine::CollisionCheckPP(std::vector<SDL_Rect> A, std::vector<SDL_Rect> B)
{

	for(int x = 0; x < A.size(); x++)
	{

		for(int y = 0; y < B.size(); y++)
		{
			if(CollisionCheck(A[x], B[y]))
				return true;
		}
	}

	return false;
}

bool engine::CollisionCheckCirc()
{
	//I don't really do anything at the moment but I am not needed currently
	//I am sad and unloved by my creator

	//TODO: Implement this at some point too whether or not you need it
	//Implementation of this will require another class of type circle
	//with attributes x, y, and radius and a few other funtions that
	//are used to calculate trajectory.

	return false;
}

/*
 * Sets the transparency color to that of the color of the input pixel
 */
void engine::setColorKeyT(SDL_Surface *surface, Uint32 pixel)
{
	if(surface != NULL)
	{
		SDL_SetColorKey(surface, SDL_SRCCOLORKEY, pixel);
	}
}

/*
 * Returns the pixel at location x, y in the image
 */
Uint32 engine::getPixel(SDL_Surface *surface, int x, int y)
{
	Uint32 *pixels = (Uint32 *)surface->pixels;

	return pixels[(y * surface->w) + x];
}

/*
 * Very powerful function
 * use with caution
 */
void engine::setPixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
{
	Uint32 *pixels = (Uint32 *)surface->pixels;

	pixels[(y * surface->w) + x] = pixel;
}

void engine::printS(SDL_Surface *screen, float x, float y, std::string s)
{
	SDL_Color color = {0,0,0};
	SDL_FreeSurface(text);
	text = TTF_RenderText_Solid(font, s.c_str(), color);
	apply_surface(x, y, text, screen, NULL);
}

SDL_Surface* engine::FlipImage(SDL_Surface *source, int flags)
{
	/*
	 * TODO: This creates a memory leak
	 * ...Problems for future self lol
	 */

	SDL_Surface *flippedimage = NULL;

	if(source->flags & SDL_SRCCOLORKEY)
	{
		flippedimage = SDL_CreateRGBSurface( SDL_SWSURFACE, source->w, source->h, source->format->BitsPerPixel, source->format->Rmask, source->format->Gmask, source->format->Bmask, 0 );
	}
	else
	{
		flippedimage = SDL_CreateRGBSurface( SDL_SWSURFACE, source->w, source->h, source->format->BitsPerPixel, source->format->Rmask, source->format->Gmask, source->format->Bmask, source->format->Amask );
	}

	if(SDL_MUSTLOCK(source))
	{
		SDL_LockSurface(source);
	}

	for(int x = 0, rx = flippedimage->w-1; x < flippedimage->w; x++, rx--)
	{
		for(int y = 0, ry = flippedimage->h-1; y < flippedimage->h; y++, ry--)
		{
			 Uint32 pixel = getPixel( source, x, y );

			 if( ( flags & FLIP_VERTICAL ) && ( flags & FLIP_HORIZONTAL ) )
			 {
				 setPixel( flippedimage, rx, ry, pixel );
			 }
			 else if( flags & FLIP_HORIZONTAL )
			 {
				 setPixel( flippedimage, rx, y, pixel );
			 }
			 else if( flags & FLIP_VERTICAL )
			 {
				 setPixel( flippedimage, x, ry, pixel );
			 }
		}
	}

	if(SDL_MUSTLOCK(source))
	{
		SDL_UnlockSurface(source);
	}

	if(source->flags & SDL_SRCCOLORKEY)
	{
		SDL_SetColorKey(flippedimage, SDL_RLEACCEL | SDL_SRCCOLORKEY, source->format->colorkey);
	}

	return flippedimage;
}

void engine::updatexy(int x, int y)
{
	lmx = mousex;
	lmy = mousey;
	mousex = x;
	mousey = y;
}

void engine::updaterelative(int x, int y)
{
	mxrel = x + c.getx();
	myrel = y + c.gety();
}

void engine::getxy(int* x, int* y)
{
	*x = mousex;
	*y = mousey;
}

void engine::getxyrel(int* x, int* y)
{
	*x = mxrel;
	*y = myrel;
}

void engine::camreset(int w, int h)
{
	c.reset(w, h);
}

void engine::camupdate(int x, int y)
{
	c.CameraRect.x -= x;
	c.CameraRect.y -= y;
}

void engine::camgetxy(int* x, int* y)
{
	*x = c.CameraRect.x;
	*y = c.CameraRect.y;
}

void engine::setFont(std::string filename, int fontsize)
{
	font = TTF_OpenFont(filename.c_str(), fontsize);
	if(!font)
	{
		exit(EXIT_FAILURE);
	}
}

void engine::newlayer(int i)
{
	std::list<lrecord>::iterator lit = layers.begin();
	while(lit != layers.end())
	{
		if(lit->layer == i)
		{
			return;
		}
	}
	layers.push_back(lrecord(true, i));
}

void engine::showLayer(int i)
{
	std::list<lrecord>::iterator lit = layers.begin();
	while(lit != layers.end())
	{
		if(lit->layer == i)
		{
			lit->vis = true;
			return;
		}
	}
}

void engine::hideLayer(int i)
{
	std::list<lrecord>::iterator lit = layers.begin();
	while(lit != layers.end())
	{
		if(lit->layer == i)
		{
			lit->vis = false;
			return;
		}
	}
}

bool engine::islayer(int i)
{
	std::list<lrecord>::iterator lit = layers.begin();
	while(lit != layers.end())
	{
		if(lit->layer == i)
		{
			return true;
		}
	}
	return false;
}

bool engine::breakdown()
{
	//TODO: Take care of cleanup of engine class when exiting
	return true;
}
